//
//  RSAUtil.m
//  X_Project_iOS
//
//  Created by 赵梁 on 16/1/15.
//  Copyright © 2016年 zhaoliang. All rights reserved.
//

#import "RSAUtil.h"

#import <CommonCrypto/CommonCrypto.h>

@implementation RSAUtil

// 我们在前面使用openssl生成的public_key.der文件的base64值，用你自己的替换掉这里
#define RSA_KEY_BASE64 @"MIIC5DCCAk2gAwIBAgIJALUk4hrYth9oMA0GCSqGSIb3DQEBBQUAMIGKMQswCQYDVQQGEwJ\
DTjERMA8GA1UECAwIU2hhbmdoYWkxETAPBgNVBAcMCFNoYW5naGFpMQ4wDAYDVQQKDAVCYWl5aTEOMAwGA1UECwwFQmFpeWk\
xEDAOBgNVBAMMB1lvcmsuR3UxIzAhBgkqhkiG9w0BCQEWFGd5cTUzMTk5MjBAZ21haWwuY29tMB4XDTExMTAyNjAyNDUzMlo\
XDTExMTEyNTAyNDUzM1owgYoxCzAJBgNVBAYTAkNOMREwDwYDVQQIDAhTaGFuZ2hhaTERMA8GA1UEBwwIU2hhbmdoYWkxDjA\
MBgNVBAoMBUJhaXlpMQ4wDAYDVQQLDAVCYWl5aTEQMA4GA1UEAwwHWW9yay5HdTEjMCEGCSqGSIb3DQEJARYUZ3lxNTMxOTk\
yMEBnbWFpbC5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAK3cKya7oOi8jVMkRGVuNn/SiSS1y5knKLh6t98JukB\
DJZqo30LVPXXL9nHcYXBTulJgzutCOGQxw8ODfAKvXYxmX7QvLwlJRFEzrqzi3eAM2FYtZZeKbgV6PximOwCG6DqaFqd8X0W\
ezP1B2eWKz4kLIuSUKOmt0h3RpIPkatPBAgMBAAGjUDBOMB0GA1UdDgQWBBSIiLi2mehEgi/MwRZOld1mLlhl7TAfBgNVHSM\
EGDAWgBSIiLi2mehEgi/MwRZOld1mLlhl7TAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAB0GUsssoVEDs9vQxk0\
DzNr8pB0idfI+Farl46OZnW5ZwPu3dvSmhQ+yRdh7Ba54JCyvRy0JcWB+fZgO4QorNRbVVbBSuPg6wLzPuasy9TpmaaYaLLK\
Iena6Z60aFWRwhazd6+hIsKTMTExaWjndblEbhAsjdpg6QMsKurs9+izr"

//生成密钥证书
+ (SecKeyRef)createSecKeyWithPubilcKeyData:(NSData *)publicKeyData
{
    if (publicKeyData==nil) {
        return nil;
    }
    
    //生成密钥证书
    SecCertificateRef myCertificate =  SecCertificateCreateWithData(kCFAllocatorDefault, (CFDataRef)publicKeyData);
    SecPolicyRef myPolicy = SecPolicyCreateBasicX509();
    SecTrustRef myTrust;
    OSStatus status = SecTrustCreateWithCertificates(myCertificate,myPolicy,&myTrust);
    SecTrustResultType trustResult;
    if (status == noErr) {
        status = SecTrustEvaluate(myTrust, &trustResult);
    }
    
    SecKeyRef publicKey = SecTrustCopyPublicKey(myTrust);
    CFRelease(myCertificate);
    CFRelease(myPolicy);
    CFRelease(myTrust);
    
    return publicKey;
}

//生成密钥证书
+ (SecKeyRef)createSecKeyWithPubilcKeyString:(NSString *)publicKeyBase64String
{
    //base64解密
    NSData *certificateData = [[NSData alloc]initWithBase64EncodedString:publicKeyBase64String options:NSDataBase64DecodingIgnoreUnknownCharacters];

    SecKeyRef publicKey = [self createSecKeyWithPubilcKeyData:certificateData];
    return publicKey;
}

//从RSA密钥证书获取密钥
+ (SecKeyRef)createSecKeyWithPubilcKeyPath:(NSString *)publicKeyPath
{
    if (publicKeyPath == nil) {
        NSLog(@"Can not find pub.der");
        return nil;
    }
    
    NSData *publicKeyFileContent = [NSData dataWithContentsOfFile:publicKeyPath];
    if (publicKeyFileContent == nil) {
        NSLog(@"Can not read data from pub.der");
        return nil;
    }
    
    SecKeyRef publicKey = [self createSecKeyWithPubilcKeyData:publicKeyFileContent];
    
    return publicKey;
}

static SecKeyRef _public_key = nil;
+ (SecKeyRef)getPublicKey
{ // 从公钥证书文件中获取到公钥的SecKeyRef指针
    if(_public_key == nil){
        [self createSecKeyWithPubilcKeyString:RSA_KEY_BASE64];
    }
    return _public_key;
}

#pragma mark - 加解密

+ (NSString*)RSAEncodeString:(NSString*)string withKeyString:(NSString *)keyString
{
    NSData *dataContent = [string dataUsingEncoding:NSUTF8StringEncoding];
    NSData *returnData = [self RSAEncodeData:dataContent withKeyString:keyString];
    NSString *retrunStr = [[NSString alloc] initWithData:returnData encoding:NSUTF8StringEncoding];
    
    return retrunStr;
}

+ (NSData*)RSAEncodeData:(NSData*)content withKeyString:(NSString *)keyString
{
    SecKeyRef secKey = [self createSecKeyWithPubilcKeyString:keyString];
    NSData *returnData = [self RSAEncodeData:content withKey:secKey];
    return returnData;
}

+ (NSData*)RSAEncodeData:(NSData*)content withKey:(SecKeyRef)key
{
    if (key == nil) {
        return nil;
    }

    if (!content) {
        return nil;
    }
    
    size_t cipherLen = SecKeyGetBlockSize(key);
    uint8_t *cipher = malloc(cipherLen * sizeof(uint8_t));
    
    size_t blockSize = cipherLen - 11;
    size_t blockCount = (size_t)ceil([content length] / (double)blockSize);
    NSMutableData *encryptedData = [[NSMutableData alloc] init];
    for (int i=0; i<blockCount; i++) {
        NSUInteger bufferSize = MIN(blockSize,[content length] - i * blockSize);
        NSData *buffer = [content subdataWithRange:NSMakeRange(i * blockSize, bufferSize)];
        OSStatus status = SecKeyEncrypt(key,
                                        kSecPaddingPKCS1,
                                        (const uint8_t *)[buffer bytes],
                                        [buffer length],
                                        cipher,
                                        &cipherLen);
        if (status == noErr){
            NSData *encryptedBytes = [[NSData alloc] initWithBytes:(const void *)cipher length:cipherLen];
            [encryptedData appendData:encryptedBytes];
        } else {
            if (cipher) free(cipher);
            return nil;
        }
    }
    if (cipher) free(cipher);
    return encryptedData;
}

@end


